﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Gwn.Library.MvpVm.Base;
using Gwn.Library.MvpVm.Events;
using Gwn.Library.MvpVm.Extensions;
using Gwn.Library.MvpVm.Interfaces;
using Gwn.Library.MvpVm.Types;
using Microsoft.Practices.Unity;

namespace Gwn.Library.MvpVm.Modules
{
    /// <summary>
    /// Application controller
    /// </summary>
    public class ApplicationControllerModule : ModuleBase, IApplicationController
    {
        private readonly List<IPresenter> _viewList = new List<IPresenter>();

        /// <summary>
        /// Registers the types.  Called before RegisterViews()
        /// </summary>
        protected override void RegisterTypes()
        {
            base.RegisterTypes();

            EventAggregator.GetEvent<ProcessEvent>().Subscribe(HandleProcessEvent, true);
        }

        /// <summary>
        /// Handles the process event.
        /// </summary>
        /// <param name="e">The <see cref="Gwn.Library.MvpVm.Events.ProcessEventArgs"/> instance containing the event data.</param>
        public void HandleProcessEvent(ProcessEventArgs e)
        {
            var processType = e.ProcessType.GetProcessType<ProcessType>();

            switch(processType)
            {
                case ProcessType.ActivateView:
                    break;

                case ProcessType.NewView:
                    _viewList.Add(e.GetData<IPresenter>());
                    break;
            }

        }


        /// <summary>
        /// Gets or sets the get presenter list.
        /// </summary>
        /// <value>The get presenter list.</value>
        public List<IPresenter> GetPresenterList ()
        {
            return _viewList;
        }

        protected override Interfaces.IPresenter RegisterViews()
        {
            // Register this controller with the container as a singleton
            Container.RegisterInstance<IApplicationController>(this,new ContainerControlledLifetimeManager());


            // This module does not have a presenter
            return null;
        }

        /// <summary>
        /// Activates the view.
        /// </summary>
        /// <param name="presenterName">Name of the view.</param>
        public void ActivateView(string presenterName)
        {
            var type = GetPresenterFromName(presenterName);
            if(type!=null)
                ActivateView(type.GetType());
        }

        /// <summary>
        /// Activates the view.
        /// </summary>
        /// <param name="presenterType">Type of the view.</param>
        public void ActivateView(Type presenterType)
        {

            // Activate by type - ensure only one view is visible at any given time
            foreach (var item in _viewList)
            {
                // Make active view visible - all others collapsed
                var view = item.View as UserControl;
                view.Visibility = item.GetType().Name == presenterType.Name
                    ? Visibility.Visible
                    : Visibility.Collapsed;

                // Set active presenter flag
                item.IsActivePresenter = (view.Visibility == Visibility.Visible);

                // Raise ViewActivated event on presenter
                if (view.Visibility == Visibility.Visible)
                {
                    var presenter = GetPresenterFromViewType(presenterType);
                    if (presenter != null)
                        presenter.ViewActivated();

                }
            }            
        }

        private IPresenter GetPresenterFromName(string name)
        {
            var viewSrch = _viewList
                .Where(item => item.View.GetType().Name == name)
                .Select(item => item)
                .FirstOrDefault();

            if (viewSrch != null)
                return viewSrch;

            var presenterSrch = _viewList
                .Where(item => item.GetType().Name == name)
                .Select(item => item)
                .FirstOrDefault();

            return presenterSrch;
        }

        private IPresenter GetPresenterFromViewType(Type presenterType)
        {
            return _viewList
                .Where(item => item.GetType().Name == presenterType.Name)
                .Select(item => item)
                .FirstOrDefault();
        }


    }
}
